-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Tweak RFC 246 with lessons learned from implementing #362
Tweak RFC 246 with lessons learned from implementing #362
Conversation
I hope this is not too off-topic or too bikesheddy, but could we also address the naming conventions of the two different categories? I proposed on Discuss that const identifiers be written in CamelCase, just like enum variants, to convey that they too are values without a significant address. From the RFC:
|
Currently we've been putting conventions like naming through RFCs as well (see some of @aturon's recent RFCs), and I imagine that a convention such as that would also need to go through the RFC process. It does seem pretty separate from this itself as this has more to do with the technical nuances of |
@alexcrichton
And what about a common case - static strings?
Interestingly, generic
All instantiations of |
That is correct, large constant arrays likely don't want to actually be constants, they want to be a Note, however, that this is not a problem for slices because the value of a slice is actually just two pointers. In the case of a |
Given that the rust PR says that the const implementation behaves like #define, what's the point behind keeping the type after the name? |
## Patterns | ||
|
||
Today, a `static` is allowed to be used in pattern matching. With the | ||
introduction of `const`, however, a `static` will be forbidden from appearning |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"appearing"
Added a note about disallowing interior borrows of statics as learned from @pcwalton's review. |
@alexcrichton Can we avoid inlining Also can the lifetime of |
A strong -1 to going further down this road from me. Performance / size concerns / compile-time have been completely ignored and the justification for removing Inlining the definitions across crate boundaries does not interfere with mutability or even significant addresses if |
C++ has mutable globals and constants with the ability to have inner mutability in those constants. The need to treat those constants as mutable global variables internally is an implementation detail. There is no reason that those implementation details need to include lack of |
I also think the fact that |
We could implement I don't see how the "expand in place" behavior of |
It can work exactly like
Making this the default / only option was already accepted earlier but not yet implemented. Having an insignificant address is in no way incompatible with mutable data. Neither is inlining of definitions thanks to the semantics of |
Making |
Why? It's already the only option for functions and there isn't a use case for significant addresses. Defining a type and using |
I actually don't think there's a point of having |
I don't see how you solve the fundamental problem of "sometimes I want the actual value of my constant to be part of my interface, but sometimes I want the actual value of my constant to be part of my implementation" in, for example, a dynamic linking scenario without a distinction between That is, what if I want to change my constant without breaking downstream crates? (Assume we had a stable ABI here) |
The compiler is free to inline the definitions across crates for all globals, including mutable ones, as long as they are marked Guaranteeing that the |
@pcwalton: The same problem exists for functions (manual cross-crate inlining is a wart - the compiler can and should do it automatically without much effort) and the solution is already |
(and there's no reason for |
Going down this road actually means we need to keep a way of marking unnamed addresses forever, because I don't think there's actually a valid reason to want to opt-out if it was the default so that would eliminate the complexity. Defining types makes more sense as a way to create a unique id since it doesn't imply overhead by default. You only pay for it when you explicitly make use of |
Manual cross-crate inlining is not a wart and is part of the design of Rust. The fact that the guts of a non-generic function can be changed without breaking downstream callers by default (i.e. without opt-in) is an important feature of C and C++, and Rust needs to support that. Separate compilation is important for many use cases; if you require The To be clear, I would have no problem with supporting |
Rust doesn't have a stable ABI for many reasons including features like Even with all of those issues fixed, altering a generic function or the private representation of a public type will break the ABI. Exposing a stable ABI requires putting a lot of care into the design of every type and function. For example, types will either need to stick with a frozen representation (possibly with unused padding fields for future expansion) or use the PIMPL idiom via Very few crates are going to be designed to have a stable ABI, and it doesn't make sense to force manual inline annotations in crates without one because it can be done by the compiler with a bit of effort put into it. It would be simple enough to offer the ability to opt-out of automatic cross-crate inlining.
There is no reason for |
As usual, an RFC by a Mozilla developer is accepted without addressing any of the concerns. The RFC continues to make many false claims. I don't see how this process has any legitimacy at all. |
|
It being an rvalue instead of an lvalue is not an implementation detail. There is no good reason for crippling it like that. The decision to make |
The fact that I addressed your concerns in my previous message and implying malice is inappropriate. This is technical disagreement. |
It's not technical disagreement. There has been no justification for it being an rvalue instead of an lvalue. There has been no justification for making statics have significant addresses. As I have stated countless times without being listened to, insignificant addresses are entirely orthogonal to mutability and there is no reason to avoid |
Since it doesn't allow taking an |
I agree that I do not see a need to make constants rvalues (and that was in fact something I brought up at the meeting). However, the decision was made because this design is a purely conservative improvement to the current system. Making constants lvalues is an improvement that can be made later. The ABI stability, and more importantly, semantic difference between interface and implementation, issue, however, is something that was considered important. Evidently you do not consider that important. That is a simple technical disagreement, and the core team decided this way on the issue. |
You're going out of your way to misrepresent my statements my statements. Here is what I just wrote:
Since you rejected the bugs I filed about ABI compatibility as relevant to backwards compatibility, I find your claim that it's me who doesn't care about it pretty laughable. |
It would be a backwards incompatible change. It's possible to move out of an rvalue but not out of an lvalue. It would make a lot more sense to define an incredibly basic
The decision to make Using types and |
I'm sorry, but I don't understand the point you're trying to make (and the hostility is making it even more difficult). My opinion that ABI stability is a worthwhile post-1.0 goal. That implies that we should not make decisions that make that difficult or impossible. That said, the fact that the implementation of certain APIs that are not going to be stable at 1.0 are currently precluding ABI stability does not prevent us from reaching that goal. Inlining all functions across crates and allowing the definitions of constants to be inlined would, however. On a meta-point, I don't think this RFC is the best place to discuss whether ABI stability should be important to Rust. I think that deserves a more holistic discussion. Much of the disagreement seems to stem from a difference of opinion regarding whether we should care about ABI stability. (I should note, however, that I find the argument about interface versus implementation to be compelling--for statics, the precise value is not considered part of a crate's interface, while for constants, it is; this gives your library users an important clue as to whether they should be relying on the value to change or not). |
That's a good point regarding backwards compatibility of making constants lvalues, but we could just promote constants to rvalues if moving would produce an error. (Moving out of a constant is rare anyway because they're usually implicitly copyable, as they're static.) The rationale for making addresses significant, as I recall, was to eliminate the hazard when people do use statics as unique identifiers (as they will anyway regardless of what we say). I personally don't really care too much one way or another. |
Statics essentially have insignificant addresses even without |
Presumably Rust is not allowed to do that for statics. (That should be clarified in the RFC.) |
Losing no overhead zero-size statics would be bad because zero-size types are a useful abstraction, as is defining a static with one. It could have very specific language forbidding the removal of unused fields from a |
Do you have a use case for a zero-sized static? Like I said I don't have strong feelings either way but I am curious what the use case is that couldn't be better done another way. I suppose you could have a struct in a static that is never used (so all its fields get optimized out) but then you might as well remove the static as well! (Unless you're only taking the static's address--but that is precisely where having significant addresses helps.) |
They're useful for implementations of traits without state. It allows obtaining an
Defining a type and |
|
If you can obtain a |
Don't you need to be able to move out of constants for mutex initializers to work? |
A few surprises were uncovered while working on RFC PR #246 (formerly known as RFC 69) with reference to globals referencing globals, and some clarifications about globals in patterns was added.